<?
/**
 *账单类——线下支付账单
 *调用getbill()生成供应商和下属分销商的账单,作为对照数据.
 */
class BillPay{
    /**
     *分销商id
     *@var int
     */
    private $fid;
    
     /**
     *供应商id
     *@var int
     */
    private $aid;
    
     /**
     *出账配置,键值数组
     *@var array
     */
    private $configs;
    
    /**
     *票付通内部接口对象
     *@var object
     */
    private $s;
    
    /**
     *数据库对象
     *@var object
     */
    private $db;
    private $payType = 0;

    /**
     * 线下支付订单
     */
    const PAY_OFFLINE = 0;
    /**
     * 在线支付订单
     */
    const PAY_ONLINE  = 1;

    /**
     *构造函数.
     *初始化内部变量.
     *@param int $fid 分销商id
     *@param int $aid 供应商id
     *@param object $s 票付通内部接口对象
     *@param object $db 数据库对象
     *@param int $payType 订单支付方式0现场执法，1在线支付
     */
    public function __construct($fid, $aid, $s, $db, $payType=0){
        $this->aid=$aid;
        $this->fid=$fid;
        $this->s=$s;
        $this->db=$db;
        $this->payType = $payType;
        $str="select `id`, `fid`, `aid`, `stype`, `status`, `billdate`,`smethod`,"
            ."`begintime` FROM uu_settle where fid=$fid and aid=$aid LIMIT 1";
        $this->db->query($str);
        $this->configs=$this->db->fetch_assoc();
    }
    
    /**
     *生成账单函数.
     *根据配置数据，产生对应的账单记录。
     */
    public function getbill(){
        $configs=$this->configs;
        $begintime=$configs['begintime'];
        $billdate=$configs["billdate"];
        $smethod=$configs["smethod"];
        $aid=$this->aid;
        $fid=$this->fid;
        $str="select max(etime) as btime from uu_bill_offline where aid=$aid and fid=$fid AND btype={$this->payType}";
        $this->db->query($str);
        $this->db->fetch_assoc();
        $btime=$this->db->f('btime');
        $btime=($btime<=$begintime)?strtotime($begintime):(strtotime($btime)+1);
//        $nowtime=time();
        $days=ceil(($_SERVER['REQUEST_TIME']-$btime)/24/3600);
        switch($smethod){
            case "2"://日结
                $limittime=time()-360*24*3600;//限制起始结算时间
                if($btime<=$limittime) return 0;
                $billdate=str_pad($billdate,2,"0",STR_PAD_LEFT);
                for($i=0;$i<$days;$i++){
                    $btimeDate=date("Y-m-d H:i:s",$btime);
                    $etime=$btime+24*3600;
                    $etimeDate=date("Y-m-d $billdate:00:00",$etime);
                    if($etimeDate>date("Y-m-d H:00:00")) break;
                    $this->get($btimeDate,$etimeDate);
                    $btime=strtotime($etimeDate)+1;//结束时间作为下一天起始时间
                }
                break;
            case "0"://月结
                if($days<14) break;//不满一个月跳出
                $sday=$billdate;
                for($i=0;$i<$days;$i++){
                    $btimeDate=date("Y-m-d H:i:s",$btime);
                    $year=date("Y",$btime);
                    $month=date("n",$btime);
                    $day=date("j",$btime);
                    if($day<$sday){
                        $etimeDate=$this->getEndDate($year,$month,$sday);
                    }else{
                        $month++;
                        if($month==13){
                            $month=1;
                            $year++;
                        }
                        $etimeDate=$this->getEndDate($year,$month,$sday);
                    }
                    if($etimeDate>=date("Y-m-d")) break;
                    $etimeDate=$etimeDate." 23:59:59";
                    $this->get($btimeDate,$etimeDate);
                    $btime=strtotime($etimeDate)+1;
                }
            break;
            case "1"://半月结
                $sday=$billdate;
                for($i=0;$i<$days;$i++){
                    $btimeDate=date("Y-m-d H:i:s",$btime);
                    $year=date("Y",$btime);
                    $month=date("n",$btime);
                    $day=date("j",$btime);
                    if($day<$sday){
                        $etimeDate=$this->getEndDate($year,$month,$sday);
                    }else{
                        $monthdays=date("t",$btime);
                        $etimeDate=$year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-".$monthdays;
                    }
                    if($etimeDate>=date("Y-m-d")) break;
                    $etimeDate=$etimeDate." 23:59:59";
                    $this->get($btimeDate,$etimeDate);
                    $btime=strtotime($etimeDate)+1;
                }
            break;
            default:break;
        }
    }
    
    /**
     *订单统计函数.——只统计现场支付的订单
     *调用接口，直接统计已完成,授信支付的订单。
     *@param date $btimeDate 完成开始时间
     *@param date $etimeDate 完成结束时间
     *@return array  array(0=>总订单数,1=>总票数,2=>总金额)
     */
    public function ordersCount($btimeDate,$etimeDate){

        $params=array(
            "btime3"    => $btimeDate,
            "etime3"    => $etimeDate,
            "status"    => "1|6",
            "pays"      => $this->payType,
            "orderby"   => 1,
            "sort"      => 1,
            "rstart"    => 0,
            "n"         => 99999,
            "c"         => 0,
            "stype"     => 0,
            "payinfo"   => "",
            "pmode"     => 0,
            "remotenum" => "",
            "origin"    => 0,
            "p_type"    => "",
            "order_confirm"=>"",
            "concat"    => 0,
            "aid"       => $this->aid,
            "mid"       => $this->fid,
            "ifpack"    => 0
        );
//        print_r($params);
        extract($params);
        $xml=$this->s->Order_Globle_Search($sid,$mid,$lid,$tid,$ltitle,$ttitle,
            $btime1,$etime1,$btime2,$etime2,$btime3,$etime3,$ordernum,$oname,
            $otel,$status,$pays,$fromt,$orderby,$sort,$rstart,$n,$c,$stype,
            $payinfo,$pmode,$remotenum,$origin,$p_type, $order_confirm,$aid,
            $concat,$ifpack);
        $orderList = simplexml_load_string($xml);
//        print_r($orderList);
//        return 0;
        if (!$orderList) {
           return 0;
        }
//        print_r($orderList);
        // 佣金公式：零售价-结算价（注意是与谁的结算价）
        // 应付款账单账单明细：零售价 - 分销给下级的价格
        // 应收款账单账单明细：零售价 - 上级供应价的价格
        $totalOrder     = $totalOrderMoney = $totalNum = 0;
        $cut_key_arr    = array('UUlprice', 'UUtotalmoney');
        foreach ($orderList as $order) {
            $mid        = (int)$order->UUmid;
            $aid        = (int)$order->UUaid;
            $sellid     = (int)$order->UUsellid;
            $totalMoney = (int)$order->UUtotalmoney;
            $tnum       = (int)$order->UUtnum;
            $buyid      = (int)$order->UUbuyid;
            $tprice     = (int)$order->UUtprice;//最终购买价格
            $aprice     = (int)$order->UUaprice;//原始供货价
            //UUlprice
            $Money     = (int)$order->$cut_key_arr[$this->payType];//用来减的价格，现场支付用零售价，在线支付用支付的总金额

            //供应商给分销商钱

            $totalOrder         += 1;//订单数
            $totalNum           += $tnum;//总票数
//            echo "订单号：" . $order->UUordernum . ";";
            if (strpos((string)$order->UUaids, ',')!==false) {
                //TODO::转分销订单
                $aids = explode(',', (string)$order->UUaids);
                array_unshift($aids, $mid);//加入最终购买的分销商ID
                $aids = array_reverse($aids);//设置销售关系链，由下往上

                $aids_price = explode(',', (string)$order->UUaids_price);

                array_unshift($aids_price, $aprice);//加入最终上级给下级的价格
                array_unshift($aids_price, $tprice);//加入最终购买的价格
                $aids_price = array_reverse($aids_price);//设置销售价格关系链，由下往上
//                print_r($aids);
                foreach ($aids as $key=>$aid) {
                    if ($aid==$this->fid) {
//                        echo "AID={$this->aid},FID={$this->fid}";
//                        echo "earn:{$Money}-{$aids_price[$key]}=". ($Money - $aids_price[$key]). "\n";
                        $totalOrderMoney += $Money - $aids_price[$key];//佣金
                        break;
                    }
                }
            }
            else {
                //TODO::直销订单
//                echo "直销订单(AID={$this->aid},FID={$this->fid}) = {$Money} - {$tprice}=" .($Money - $tprice) . "\n";
                $totalOrderMoney    += ($Money - $tprice);//应付款=零售价 - 分销给下级的价格
            }

        }
        return array($totalOrder, $totalNum, $totalOrderMoney);
//        return explode(",",$count);
    }
    
    /**
     *订单统计明细函数.
     *调用接口，返回传入时间段的simplexml数据记录。
     *@param date $btimeDate 完成开始时间
     *@param date $etimeDate 完成结束时间
     *@return simplexml
     */
    public function ordersDetail($btimeDate,$etimeDate){
        $params=array(
            "btime3"=>$btimeDate,
            "etime3"=>$etimeDate,
            "status"=>"1|6",
            "pays"  => $this->payType,
            "orderby"=>1,
            "sort"=>1,
            "rstart"=>0,
            "n"=>9999999,
            "c"=>0,
            "stype"=>2,
            "payinfo"=>"2",
            "pmode"=>0,
            "remotenum"=>"",
            "origin"=>0,
            "p_type"=>"",
            "order_confirm"=>"",
            "concat"=>0,
            "aid"=>$this->aid,
            "mid"=>$this->fid,
            "ifpack"=>0);
        extract($params);
        $xml=$this->s->Order_Globle_Search($sid,$mid,$lid,$tid,$ltitle,$ttitle,$btime1,$etime1,$btime2,$etime2,$btime3,$etime3,$ordernum,$oname,$otel,$status,$pays,$fromt,$orderby,$sort,$rstart,$n,0,$stype,$payinfo,$pmode,$remotenum,$origin,$p_type, $order_confirm,$aid,$concat,$ifpack);
        return simplexml_load_string($xml);
    }
    
    /**
     *
     * 账单记录函数.将指定时间段的账单记录记到数据库。
     *
     * @param string $btimeDate 完成开始时间
     * @param string $etimeDate 完成结束时间
     * @return bool
     * @uses Bill::getbill()
     */
    public function get($btimeDate, $etimeDate){
        $fid    = $this->fid;
        $aid    = $this->aid;
        $str    = "SELECT id FROM uu_bill_offline WHERE fid=$fid AND aid=$aid"
            ." AND btime='$btimeDate' AND etime='$etimeDate' AND btype={$this->payType} LIMIT 1";
        $GLOBALS['le']->query($str);
        if(!$GLOBALS['le']->fetch_assoc()){//确保记录唯一
//            echo PHP_EOL . $btimeDate,'===',$etimeDate . PHP_EOL;
            $count  = $this->ordersCount($btimeDate,$etimeDate);
            if ($count===0) return false;
            $orders = $count[0];
            $tnums  = $count[1];
            $money  = $count[2];

            $str=<<<SQL
insert uu_bill_offline set fid=$fid,aid=$aid,btime='$btimeDate',
etime='$etimeDate',orders=$orders,tnums=$tnums,money=$money,
btype={$this->payType},addtime=now()
SQL;
//            echo "SQL=".$str . PHP_EOL;
            $GLOBALS['le']->query($str);
        }
    }
    
    /**
     *获得正确日期.
     *如果设置的出账日期不存在如 2013-02-31
     *就递归减小到正确日期.
     *@param int year  年
     *@param int month 月
     *@param int day   日
     *@return date
     *@uses Bill::getbill
     */
    public function getEndDate($year,$month,$day){
        if($month>12||$month<0||$day<0||$year<0) return false;
        if(checkdate($month,$day,$year)){
            return $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-".str_pad($day,2,"0",STR_PAD_LEFT);
        }else{
            return $this->getEndDate($year,$month,$day-1);
        }
    }
}
?>